class Compialer {
    constructor(vm) {
        this.el = vm.$el
        this.vm = vm
        this.methods = vm.$methods
        this.compialer(vm.$el)
    }

    // 编译节点 处理文本节点和元素节点
    compialer(el) {
        const childnodes = el.childNodes
        Array.from(childnodes).forEach(node => {
            if (this.istextNode(node)) {
                // 说明是文本节点
                this.compialerText(node)
            } else if (this.isElementNode(node)) {
                // 说明是元素节点
                this.compialerElement(node)
            }
            if (node.childNodes && node.childNodes.length) {
                // 如果节点中还有子元素的话 要递归调用
                this.compialer(node)
            }
        })
    }

    // 编译元素节点，处理指令
    compialerElement(node) {
        // 遍历所有的属性节点
        Array.from(node.attributes).forEach(attr => {
            // 判断是否是指令
            let attrName = attr.name
            if (this.isDirective(attrName)) {
                // 是指令  将 v-text ==> text
                attrName = attrName.substr(2)
                // 获取属性的值
                let key = attr.value
                this.update(node, key, attrName)

            }
        })
    }
    update(node, key, attrName) {
        if (attrName.startsWith('on:')) {
            const reg =/(?<=(:)).*/g
            const eventName = attrName.match(reg)
            this.onUpdate.call(this, node, this.vm[key], key,eventName[0])
        } else {
            let updateFn = this[attrName + 'Update'] // 代表this.textUpdate | this.modelUpdate  attrName = text|model
            updateFn && updateFn.call(this, node, this.vm[key], key)
        }
    }
    // 处理v-text 指令
    textUpdate(node, value, key) {
        node.textContent = value
        new Watcher(this.vm, key, (newValue) => {
            node.textContent = newValue
        })
    }
    // 处理 v-html 指令
    htmlUpdate(node, value, key) {
        node.innerHTML = value
        // this.compialerHtml(node)
        new Watcher(this.vm, key, (newValue) => {
            node.innerHTML = newValue
        })
    }
    // 处理 v-on 指令
    onUpdate(node, value, key,eventName) {
        addEventListener(eventName, () => {
            if (key) {
                try{
                    
                    Object.keys(this.methods).forEach(method => {
                        const reg =/\((.+)\)/g
                        const res = key.match(reg)
                        const args = RegExp.$1
                        const argArr = args.split(',')
                        if(key.includes('(')){
                            this.methods[method](...argArr)
                            throw new Error('完成啦')
                        }else{
                            this.methods[method]()
                            throw new Error('完成啦')
    
                        }
                    })
                }catch(e){
                    if(e.message !== '完成啦' ) throw e
                }
               
            }
        })
    }
    // 处理v-model指令
    modelUpdate(node, value, key) {
        node.value = value
        new Watcher(this.vm, key, (newValue) => {
            node.value = newValue
        })

        addEventListener('input', () => {
            this.vm[key] = node.value
        })
    }
    // 编译文本节点，处理指令
    compialerText(node) {
        const reg = /\{\{(.+?)\}\}/
        const value = node.textContent
        if (reg.test(value)) {
            const key = RegExp.$1.trim()
            node.textContent = value.replace(reg, this.vm[key])

            new Watcher(this.vm, key, (newValue) => {
                node.textContent = newValue
            })
        }
    }

    // 判断是否是指令
    isDirective(attrname) {
        return attrname.startsWith('v-')
    }

    //  判断是否是文本节点
    istextNode(node) {
        return node.nodeType === 3
    }

    // 判断是否是元素节点
    isElementNode(node) {
        return node.nodeType === 1
    }
}